home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / share / pyshared / PIL / PcfFontFile.py < prev    next >
Text File  |  2006-12-03  |  6KB  |  257 lines

  1. #
  2. # THIS IS WORK IN PROGRESS
  3. #
  4. # The Python Imaging Library
  5. # $Id: PcfFontFile.py 2134 2004-10-06 08:55:20Z fredrik $
  6. #
  7. # portable compiled font file parser
  8. #
  9. # history:
  10. # 1997-08-19 fl   created
  11. # 2003-09-13 fl   fixed loading of unicode fonts
  12. #
  13. # Copyright (c) 1997-2003 by Secret Labs AB.
  14. # Copyright (c) 1997-2003 by Fredrik Lundh.
  15. #
  16. # See the README file for information on usage and redistribution.
  17. #
  18.  
  19. import Image
  20. import FontFile
  21.  
  22. import string
  23.  
  24. # --------------------------------------------------------------------
  25. # declarations
  26.  
  27. PCF_MAGIC = 0x70636601 # "\x01fcp"
  28.  
  29. PCF_PROPERTIES = (1<<0)
  30. PCF_ACCELERATORS = (1<<1)
  31. PCF_METRICS = (1<<2)
  32. PCF_BITMAPS = (1<<3)
  33. PCF_INK_METRICS = (1<<4)
  34. PCF_BDF_ENCODINGS = (1<<5)
  35. PCF_SWIDTHS = (1<<6)
  36. PCF_GLYPH_NAMES = (1<<7)
  37. PCF_BDF_ACCELERATORS = (1<<8)
  38.  
  39. BYTES_PER_ROW = [
  40.     lambda bits: ((bits+7)  >> 3),
  41.     lambda bits: ((bits+15) >> 3) & ~1,
  42.     lambda bits: ((bits+31) >> 3) & ~3,
  43.     lambda bits: ((bits+63) >> 3) & ~7,
  44. ]
  45.  
  46.  
  47. def l16(c):
  48.     return ord(c[0]) + (ord(c[1])<<8)
  49. def l32(c):
  50.     return ord(c[0]) + (ord(c[1])<<8) + (ord(c[2])<<16) + (ord(c[3])<<24)
  51.  
  52. def b16(c):
  53.     return ord(c[1]) + (ord(c[0])<<8)
  54. def b32(c):
  55.     return ord(c[3]) + (ord(c[2])<<8) + (ord(c[1])<<16) + (ord(c[0])<<24)
  56.  
  57. def sz(s, o):
  58.     return s[o:string.index(s, "\0", o)]
  59.  
  60. ##
  61. # Font file plugin for the X11 PCF format.
  62.  
  63. class PcfFontFile(FontFile.FontFile):
  64.  
  65.     name = "name"
  66.  
  67.     def __init__(self, fp):
  68.  
  69.         magic = l32(fp.read(4))
  70.         if magic != PCF_MAGIC:
  71.             raise SyntaxError, "not a PCF file"
  72.  
  73.         FontFile.FontFile.__init__(self)
  74.  
  75.         count = l32(fp.read(4))
  76.         self.toc = {}
  77.         for i in range(count):
  78.             type = l32(fp.read(4))
  79.             self.toc[type] = l32(fp.read(4)), l32(fp.read(4)), l32(fp.read(4))
  80.  
  81.         self.fp = fp
  82.  
  83.         self.info = self._load_properties()
  84.  
  85.         metrics = self._load_metrics()
  86.         bitmaps = self._load_bitmaps(metrics)
  87.         encoding = self._load_encoding()
  88.  
  89.         #
  90.         # create glyph structure
  91.  
  92.         for ch in range(256):
  93.             ix = encoding[ch]
  94.             if ix is not None:
  95.                 x, y, l, r, w, a, d, f = metrics[ix]
  96.                 glyph = (w, 0), (l, d-y, x+l, d), (0, 0, x, y), bitmaps[ix]
  97.                 self.glyph[ch] = glyph
  98.  
  99.     def _getformat(self, tag):
  100.  
  101.         format, size, offset = self.toc[tag]
  102.  
  103.         fp = self.fp
  104.         fp.seek(offset)
  105.  
  106.         format = l32(fp.read(4))
  107.  
  108.         if format & 4:
  109.             i16, i32 = b16, b32
  110.         else:
  111.             i16, i32 = l16, l32
  112.  
  113.         return fp, format, i16, i32
  114.  
  115.     def _load_properties(self):
  116.  
  117.         #
  118.         # font properties
  119.  
  120.         properties = {}
  121.  
  122.         fp, format, i16, i32 = self._getformat(PCF_PROPERTIES)
  123.  
  124.         nprops = i32(fp.read(4))
  125.  
  126.         # read property description
  127.         p = []
  128.         for i in range(nprops):
  129.             p.append((i32(fp.read(4)), ord(fp.read(1)), i32(fp.read(4))))
  130.         if nprops & 3:
  131.             fp.seek(4 - (nprops & 3), 1) # pad
  132.  
  133.         data = fp.read(i32(fp.read(4)))
  134.  
  135.         for k, s, v in p:
  136.             k = sz(data, k)
  137.             if s:
  138.                 v = sz(data, v)
  139.             properties[k] = v
  140.  
  141.         return properties
  142.  
  143.     def _load_metrics(self):
  144.  
  145.         #
  146.         # font metrics
  147.  
  148.         metrics = []
  149.  
  150.         fp, format, i16, i32 = self._getformat(PCF_METRICS)
  151.  
  152.         append = metrics.append
  153.  
  154.         if (format & 0xff00) == 0x100:
  155.  
  156.             # "compressed" metrics
  157.             for i in range(i16(fp.read(2))):
  158.                 left = ord(fp.read(1)) - 128
  159.                 right = ord(fp.read(1)) - 128
  160.                 width = ord(fp.read(1)) - 128
  161.                 ascent = ord(fp.read(1)) - 128
  162.                 descent = ord(fp.read(1)) - 128
  163.                 xsize = right - left
  164.                 ysize = ascent + descent
  165.                 append(
  166.                     (xsize, ysize, left, right, width,
  167.                      ascent, descent, 0)
  168.                     )
  169.  
  170.         else:
  171.  
  172.             # "jumbo" metrics
  173.             for i in range(i32(fp.read(4))):
  174.                 left = i16(fp.read(2))
  175.                 right = i16(fp.read(2))
  176.                 width = i16(fp.read(2))
  177.                 ascent = i16(fp.read(2))
  178.                 descent = i16(fp.read(2))
  179.                 attributes = i16(fp.read(2))
  180.                 xsize = right - left
  181.                 ysize = ascent + descent
  182.                 append(
  183.                     (xsize, ysize, left, right, width,
  184.                      ascent, descent, attributes)
  185.                     )
  186.  
  187.         return metrics
  188.  
  189.     def _load_bitmaps(self, metrics):
  190.  
  191.         #
  192.         # bitmap data
  193.  
  194.         bitmaps = []
  195.  
  196.         fp, format, i16, i32 = self._getformat(PCF_BITMAPS)
  197.  
  198.         nbitmaps = i32(fp.read(4))
  199.  
  200.         if nbitmaps != len(metrics):
  201.             raise IOError, "Wrong number of bitmaps"
  202.  
  203.         offsets = []
  204.         for i in range(nbitmaps):
  205.             offsets.append(i32(fp.read(4)))
  206.  
  207.         bitmapSizes = []
  208.         for i in range(4):
  209.             bitmapSizes.append(i32(fp.read(4)))
  210.  
  211.         byteorder = format & 4 # non-zero => MSB
  212.         bitorder  = format & 8 # non-zero => MSB
  213.         padindex  = format & 3
  214.  
  215.         bitmapsize = bitmapSizes[padindex]
  216.         offsets.append(bitmapsize)
  217.  
  218.         data = fp.read(bitmapsize)
  219.  
  220.         pad  = BYTES_PER_ROW[padindex]
  221.         mode = "1;R"
  222.         if bitorder:
  223.             mode = "1"
  224.  
  225.         for i in range(nbitmaps):
  226.             x, y, l, r, w, a, d, f = metrics[i]
  227.             b, e = offsets[i], offsets[i+1]
  228.             bitmaps.append(
  229.                 Image.fromstring("1", (x, y), data[b:e], "raw", mode, pad(x))
  230.                 )
  231.  
  232.         return bitmaps
  233.  
  234.     def _load_encoding(self):
  235.  
  236.         # map character code to bitmap index
  237.         encoding = [None] * 256
  238.  
  239.         fp, format, i16, i32 = self._getformat(PCF_BDF_ENCODINGS)
  240.  
  241.         firstCol, lastCol = i16(fp.read(2)), i16(fp.read(2))
  242.         firstRow, lastRow = i16(fp.read(2)), i16(fp.read(2))
  243.  
  244.         default = i16(fp.read(2))
  245.  
  246.         nencoding = (lastCol - firstCol + 1) * (lastRow - firstRow + 1)
  247.  
  248.         for i in range(nencoding):
  249.             encodingOffset = i16(fp.read(2))
  250.             if encodingOffset != 0xFFFF:
  251.                 try:
  252.                     encoding[i+firstCol] = encodingOffset
  253.                 except IndexError:
  254.                     break # only load ISO-8859-1 glyphs
  255.  
  256.         return encoding
  257.